/**
 * クリックで変形
 * Macのエフェクトに近いもの。
 * マウスの位置が中心になるように移動
 */
package  {
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Loader;
	import flash.display.Sprite;
	import flash.display.Stage;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.system.LoaderContext;
	import org.libspark.betweenas3.BetweenAS3;
	import org.libspark.betweenas3.tweens.ITween;
	import org.libspark.betweenas3.easing.*;
	
	[SWF(backgroundColor="0xFFFFFF", width="465", height="465", frameRate="60")]
	public class Ginnye extends Sprite{
		private var loader:Loader;
		public function Ginnye() {
			if (stage) init();
			else addEventListener(Event.ADDED_TO_STAGE, init);
		}
		
		private var cols:uint = 10;//縦の分割数
		private var rows:uint = 30;//横の分割数
		private var bitmapData:BitmapData;
		private var resolutionX:Number;
		private var resolutionY:Number;
		private var smallScale:Number = 0.1;
		private var isMinimizing:Boolean = false;
		
		private var vertices:Vector.<Number> = new Vector.<Number>();
		private var uvtData:Vector.<Number> = new Vector.<Number>();
		private var indices:Vector.<int> = new Vector.<int>();
		private var dots:Vector.<Dot> = new Vector.<Dot>();
		
		private function init(e:Event = null):void {
			removeEventListener(Event.ADDED_TO_STAGE, init);
			stage.scaleMode = StageScaleMode.NO_SCALE;
			stage.align = StageAlign.TOP_LEFT;
			
			loader = new Loader();
			loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loaderCompleteHandler);
			loader.load(new URLRequest("http://miniapp.org/wonderfl/image/baba.jpg"), new LoaderContext(true));
		}
		
		private function loaderCompleteHandler(e:Event):void {
			bitmapData = (loader.content as Bitmap).bitmapData;
			resolutionX = bitmapData.width / cols;
			resolutionY = bitmapData.height / rows;
			
			for (var yy:uint = 0; yy <= rows; ++yy) { 
				for (var xx:uint = 0; xx <= cols; ++xx) {
					
					var dot:Dot = new Dot();
					dot.index = dots.length;
					dot.x = xx * resolutionX;
					dot.y = yy * resolutionY;
					dot.originPoint = new Point(dot.x, dot.y);
					//大きくなるときのディレイ時間。上の方から動くように。
					dot.maximizeDelay = yy / 100;
					//小さくなるときのディレイ時間。下の方から動くように。
					dot.minimizeDelay = (rows - yy) / 100;
					dots.push(dot);
					
					vertices.push(dot.x, dot.y);
					uvtData.push(xx / cols, yy / rows);
					
					//一番下の段ではなく、かつ、一番右の段ではない時
					if (yy < rows && xx < cols) { 
						//今処理している点の番号
						var dotNo:uint = (cols + 1) * yy + xx;
						//次のロウの同じカラムの点の番号
						var nextRowsDotNo:uint = (cols + 1) * (yy + 1) + xx;
						
						indices.push(dotNo, dotNo + 1, nextRowsDotNo + 1);
						indices.push(dotNo, nextRowsDotNo + 1, nextRowsDotNo);
					}
				}
			}
			
            graphics.beginBitmapFill(bitmapData);
            graphics.drawTriangles(vertices, indices, uvtData);
            graphics.endFill();
			
			vertices.fixed = true;
			indices.fixed = true;
			uvtData.fixed = true;
			
			addEventListener(Event.ENTER_FRAME, enterFrameHandler);
			stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
		}
		
		private function mouseDownHandler(e:MouseEvent):void {
			var matrix:Matrix = new Matrix();
			
			if (isMinimizing) {
				//元の座標から、ｘ座標はマウスの周り、ｙ座標はそのままの座標に変形する
				matrix.translate(mouseX - bitmapData.width / 2, 0);
			}
			else {
				var smallWidth:Number = bitmapData.width * smallScale;
				var smallHeight:Number = bitmapData.height * smallScale;
				//元の座標から、ｘ座標はマウスの周り、ｙ座標は小さくなる時の座標に移動する
				matrix.scale(smallScale, smallScale);
				matrix.translate(mouseX - smallWidth / 2, stage.stageHeight - smallHeight);
			}
			
			var targetPoint:Point;
			
			for each(var dot:Dot in dots) {
				if (isMinimizing) {
					//大きくする
					targetPoint = matrix.transformPoint(dot.originPoint);
					dot.move(targetPoint.x, targetPoint.y, dot.maximizeDelay);
				}
				else {
					//小さくする
					targetPoint = matrix.transformPoint(dot.originPoint);
					dot.move(targetPoint.x, targetPoint.y, dot.minimizeDelay);
				}
			}
			
			isMinimizing = !isMinimizing;
		}
		
		private function enterFrameHandler(e:Event):void {
			draw();
		}
		
		private function draw():void {
			graphics.clear();
			
			for each(var dot:Dot in dots){
				vertices[dot.index * 2] = dot.x;
				vertices[dot.index * 2 + 1] = dot.y;
			}
			
            graphics.beginBitmapFill(bitmapData);
            graphics.drawTriangles(vertices, indices, uvtData);
            graphics.endFill();
		}
	}
}

import flash.geom.Point;
import org.libspark.betweenas3.BetweenAS3;
import org.libspark.betweenas3.easing.*;
import org.libspark.betweenas3.tweens.ITween;
class Dot { 
	public var x:Number;
	public var y:Number;
	public var index:int;
	public var originPoint:Point;
	public var minimizeDelay:Number;
	public var maximizeDelay:Number;
	private var tween:ITween;
	
	public function move(toX:Number, toY:Number, delay:Number):void {
		if (tween) tween.stop();
		
		tween = BetweenAS3.delay(
			BetweenAS3.tween(this, {x: toX, y: toY}, null, 0.4, Exponential.easeOut),
			delay
		);
		
		tween.play();
	}
}